package ar.edu.unicen.exa.isistan.archassis.ia.seed;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import ar.edu.unicen.exa.isistan.archassis.ia.api.db.JavaClass;

public class MetodoSeed implements ISeed, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private String name;
	
	private List<String> parametros;
	
	private List<Run> ejecuta = new ArrayList<Run>();
	
	private String retorna;

	private float pesoEjecuta = 0.8f;

	private float pesoParametro = 0.2f;
	
	private float peso = 1f;

	private String nameParam = "";

	
	
	public static final String UNION = "->";
	
	public MetodoSeed(String name, String retorna, List<String> parametros, List<Run> ejecuta){
		this.name = name;
		this.parametros = parametros;
		this.ejecuta = ejecuta;
		this.retorna = retorna;
	}
	
	public MetodoSeed(MetodoSeed metodo) {
		this.name = metodo.getName();
		this.parametros = metodo.getParametros();
	}
	
	//private JavaClass javaClass;
//	public void setJavaClass(JavaClass javaClass) {
//		this.javaClass = javaClass;
//	}
	public void addEjecuta(Run r){
		ejecuta.add(r);
	}

	public float getPesoEjecuta() {
		return pesoEjecuta;
	}

	public void setPesoEjecuta(float pesoEjecuta) {
		this.pesoEjecuta = pesoEjecuta;
	}

	public float getPesoParametro() {
		return pesoParametro;
	}

	public void setPesoParametro(float pesoParametro) {
		this.pesoParametro = pesoParametro;
	}

	public String getRetorna() {
		return retorna;
	}

	public void setRetorna(String retorna) {
		this.retorna = retorna;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<String> getParametros() {
		return parametros;
	}

	public void setParametros(List<String> parametros) {
		this.parametros = parametros;
	}

	public List<Run> getEjecuta() {
		return ejecuta;
	}

	public void setEjecuta(List<Run> ejecuta) {
		this.ejecuta = ejecuta;
	}

	public void setPeso(float peso) {
		this.peso = peso;
	}

	@Override
	public float eval(JavaClass c) {
		if (c.getMetodos() == null) {
			return 0;
		}
		int pos = c.getMetodos().indexOf(this);
		if(pos == -1){
			return 0;
		}
		MetodoSeed met = c.getMetodos().get(pos);
		float valorEjecuta = (float)ejecuta.size();
		float result = 1f;
		if (valorEjecuta > 0){
			/**
			 * Si ingresa tiene ejecuta, entonces:
			 * PesoParametro es el valor que ya tiene por tener el mismo nombre y los mismo parametros
			 * PesoEjecuta se divide por la cantidad que ejecuta y cada vez que la dos clases llamen al mismo ejecuta se le suma al resultado el valorEjecuta 
			 */
			valorEjecuta = pesoEjecuta  / valorEjecuta;
			result = pesoParametro ;
			for(Run ex: ejecuta){
				if(met.getEjecuta().contains(ex)){
					result += valorEjecuta;
				}
			}
		}
		return (result * peso);
		
	}

	@Override
	public void updatePeso(JavaClass c) {
		if (c.getMetodos() == null) {
			return;
		}
		int pos = c.getMetodos().indexOf(this);
		if(pos == -1){
			return;
		}
		
		MetodoSeed met = c.getMetodos().get(pos);
		float valorEjecuta = (float)ejecuta.size();
		float result = 1f;
		if (valorEjecuta > 0){
			/**
			 * Si ingresa tiene ejecuta, entonces:
			 * PesoParametro es el valor que ya tiene por tener el mismo nombre y los mismo parametros
			 * PesoEjecuta se divide por la cantidad que ejecuta y cada vez que la dos clases llamen al mismo ejecuta se le suma al resultado el valorEjecuta 
			 */
			valorEjecuta = pesoEjecuta  / valorEjecuta;
			result = pesoParametro ;
			for(Run ex: ejecuta){
				if(met.getEjecuta().contains(ex)){
					result += valorEjecuta;
				}
			}
		}
		peso = result * peso;
		
	}

	@Override
	public float getPeso() {
		return peso;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof MetodoSeed){
			if(name.equals(((MetodoSeed)obj).getName())){
				if (((MetodoSeed)obj).getParametros().size() != parametros.size()){
					return false;
				}
				for(String param: parametros){
					if(!((MetodoSeed)obj).getParametros().contains(param)){
						return false;
					}
				}
				//Si llega aca, tiene los mismos parametros y el mismos nombre
				return true;
			}
			return false;
		}
		return false;
	}
	
	/**
	 * Retorn el método como un string (paquete + clase + nombre del metodo + '(' + parametros + ')'
	 * @return
	 */
	public String getAbsoluteData() {
		StringBuffer result = new StringBuffer(retorna);
		result.append(" ");
		result.append(name);
		result.append("(");
		boolean empty = true;
		for (String parametro: parametros) {
			if (empty) {
				result.append(parametro);
				empty = false;
			} else {
				result.append(",").append(parametro);
			}
		}
		result.append(")");
		return result.toString();
	}
	public String getNameParam(){
		if(nameParam == null || nameParam.equals("")){
			nameParam  = name + " ( ";
			for (String parametro: parametros) {
				nameParam = nameParam + parametro;
			}
			nameParam = nameParam + " )";
		}	
		return  nameParam;
	}

	

}
